home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
-
- mhimdev.library - MHI driver for mpeg.device
- Copyright (C) 2001 Michael Henke
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- *****************************************************************************/
-
-
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <exec/memory.h>
- #include <exec/interrupts.h>
- #include <utility/tagitem.h>
- #include <libraries/mhi.h>
- #include <devices/melodympeg.h>
- #include "mhimdev.h"
-
- static void myDoIO(struct IOMPEGReq *mdevreq, UWORD command);
- static void __asm softint_server(register __a1 struct mhimdevHandle *h);
-
-
-
-
- struct mhimdevHandle
- {
- UBYTE mdevunit, mdevname[256], mhistatus;
- struct MsgPort *mdevport;
- struct IOMPEGReq *mdevreq;
- struct List list_unused, list_getempty;
- struct Task *mhitask;
- ULONG mhisignal;
- struct Interrupt mdevsoftint;
- LONG requests_pending;
- ULONG mhivolume, mhipanning;
- };
-
-
-
-
-
- APTR __asm
- i_MHIAllocDecoder(register __a0 struct Task *task, register __d0 ULONG mhisignal)
- {
- struct mhimdevHandle *h;
- #ifdef DEBUG
- KPutStr("MHIAllocDecoder()\n");
- #endif
- if(task==NULL) return(NULL);
- h=(struct mhimdevHandle*)AllocVec(sizeof(struct mhimdevHandle),MEMF_PUBLIC|MEMF_CLEAR);
- if(h==NULL) return(NULL);
- h->mhitask=task;
- h->mhisignal=mhisignal;
- h->mhistatus=MHIF_STOPPED;
- h->mhivolume=100;
- h->mhipanning=50;
- NewList(&h->list_unused);
- NewList(&h->list_getempty);
- {
- struct DosLibrary *DOSBase;
- UBYTE *varbuf;
- LONG varlen, args[2]={0,0};
- struct RDArgs *rdargs, *rdargs2;
- struct TagItem tagdone={TAG_DONE,0};
- if((DOSBase=(struct DosLibrary*)OpenLibrary("dos.library",37)))
- {
- if((varbuf=AllocVec(1024,MEMF_PUBLIC|MEMF_CLEAR)))
- {
- if((varlen=GetVar("MHIMDEV",varbuf,1024,LV_VAR))>0)
- {
- #ifdef DEBUG
- KPutStr("MHIMDEV varbuf=\"");
- KPutStr(varbuf);
- KPutStr("\"\n");
- #endif
- if((rdargs=AllocDosObject(DOS_RDARGS,&tagdone)))
- {
- rdargs->RDA_Source.CS_Buffer=varbuf;
- rdargs->RDA_Source.CS_Length=varlen;
- rdargs->RDA_Source.CS_CurChr=0;
- rdargs->RDA_Flags=RDAF_NOPROMPT;
- rdargs->RDA_DAList=0;
- rdargs2=ReadArgs("DEVICE,UNIT/N",args,rdargs);
- if(args[0]) CopyMem((APTR)args[0],h->mdevname,sizeof(h->mdevname)-1);
- if(args[1]) h->mdevunit=(*(LONG*)args[1]);
- FreeArgs(rdargs2);
- FreeDosObject(DOS_RDARGS,rdargs);
- }
- }
- FreeVec(varbuf);
- }
- CloseLibrary((struct Library*)DOSBase);
- }
- }
- #ifdef DEBUG
- KPutStr("MHIMDEV var: DEVICE=");
- KPutStr(h->mdevname);
- KPutStr(" UNIT=");
- KPutChar((LONG)('0'+h->mdevunit));
- #endif
- if((h->mdevport=CreateMsgPort()))
- {
- h->mdevsoftint.is_Data=(APTR)h;
- h->mdevsoftint.is_Code=(void(*)(void))softint_server;
- h->mdevport->mp_SoftInt= &h->mdevsoftint;
- h->mdevport->mp_Flags=PA_SOFTINT;
- if((h->mdevreq=(struct IOMPEGReq*)CreateIORequest(h->mdevport,sizeof(struct IOMPEGReq))))
- {
- if(OpenDevice(h->mdevname,(ULONG)h->mdevunit,(struct IORequest*)h->mdevreq,0)==0)
- {
- myDoIO(h->mdevreq,CMD_RESET);
- myDoIO(h->mdevreq,MPEGCMD_PLAY);
- h->mdevreq->iomr_Arg1=1;
- myDoIO(h->mdevreq,MPEGCMD_PAUSE);
- #ifdef DEBUG
- KPutStr(" __open ok__\n");
- #endif
- return(h);
- }
- DeleteIORequest(h->mdevreq);
- }
- DeleteMsgPort(h->mdevport);
- }
- FreeVec(h);
- #ifdef DEBUG
- KPutStr(" **open failed**\n");
- #endif
- return(NULL);
- }
-
-
-
-
-
- void __asm
- i_MHIFreeDecoder(register __a3 APTR handle)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- struct IOMPEGReq *req;
- #ifdef DEBUG
- KPutStr("MHIFreeDecoder()\n");
- #endif
- if(handle==NULL) return;
- i_MHIStop(handle);
- while((req=(struct IOMPEGReq*)RemHead(&h->list_unused)))
- FreeMem(req,sizeof(struct IOMPEGReq));
- CloseDevice((struct IORequest*)h->mdevreq);
- DeleteIORequest(h->mdevreq);
- DeleteMsgPort(h->mdevport);
- FreeVec(h);
- }
-
-
-
-
-
- BOOL __asm
- i_MHIQueueBuffer(register __a3 APTR handle, register __a0 APTR buffer, register __d0 ULONG size)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- struct IOMPEGReq *req;
- #ifdef DEBUG
- KPutStr("MHIQueueBuffer()\n");
- #endif
- if((handle==NULL) || (buffer==NULL) || (size==0)) return(FALSE);
- if(!(req=(struct IOMPEGReq*)RemHead(&h->list_unused)))
- {
- UWORD i;
- for(i=0;i<32;i++)
- {
- req=(struct IOMPEGReq*)AllocMem(sizeof(struct IOMPEGReq),MEMF_PUBLIC);
- if(req) AddTail(&h->list_unused,(struct Node*)req);
- }
- if(!(req=(struct IOMPEGReq*)RemHead(&h->list_unused)))
- return(FALSE);
- }
- CopyMem(h->mdevreq,req,sizeof(struct IOMPEGReq));
- req->iomr_Req.io_Command=CMD_WRITE;
- req->iomr_Req.io_Data=buffer;
- req->iomr_Req.io_Length=size;
- req->iomr_Req.io_Flags=0;
- req->iomr_StreamType=MPEGSTREAM_AUDIO;
- req->iomr_MPEGFlags=0;
- h->requests_pending++;
- SendIO((struct IORequest*)req);
- return(TRUE);
- }
-
-
-
-
-
- APTR __asm
- i_MHIGetEmpty(register __a3 APTR handle)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- struct IOMPEGReq *req;
- #ifdef DEBUG
- KPutStr("MHIGetEmpty()\n");
- #endif
- if(handle==NULL) return(NULL);
- Disable();
- req=(struct IOMPEGReq*)RemHead(&h->list_getempty);
- Enable();
- if(req==NULL) return(NULL);
- AddTail(&h->list_unused,(struct Node*)req);
- return(req->iomr_Req.io_Data);
- }
-
-
-
-
-
- UBYTE __asm
- i_MHIGetStatus(register __a3 APTR handle)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- #ifdef DEBUG
- KPutStr("MHIGetStatus()\n");
- #endif
- if(handle==NULL) return(MHIF_STOPPED);
- if((h->requests_pending<=0) && (h->mhistatus==MHIF_PLAYING))
- return(MHIF_OUT_OF_DATA);
- else
- return(h->mhistatus);
- }
-
-
-
-
-
- void __asm
- i_MHIPlay(register __a3 APTR handle)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- #ifdef DEBUG
- KPutStr("MHIPlay()\n");
- #endif
- if(handle==NULL) return;
- myDoIO(h->mdevreq,MPEGCMD_PLAY);
- h->mdevreq->iomr_Arg1=0;
- myDoIO(h->mdevreq,MPEGCMD_PAUSE);
- h->mhistatus=MHIF_PLAYING;
- }
-
-
-
-
-
- void __asm
- i_MHIStop(register __a3 APTR handle)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- struct IOMPEGReq *req;
- #ifdef DEBUG
- KPutStr("MHIStop()\n");
- #endif
- if(handle==NULL) return;
- Disable();
- h->mdevport->mp_Flags=PA_IGNORE;
- Enable();
- while((req=(struct IOMPEGReq*)RemHead(&h->list_getempty)))
- AddTail(&h->list_unused,(struct Node*)req);
- myDoIO(h->mdevreq,CMD_FLUSH);
- while((req=(struct IOMPEGReq*)GetMsg(h->mdevport)))
- if(req!=h->mdevreq) AddTail(&h->list_unused,(struct Node*)req);
- h->requests_pending=0;
- h->mdevreq->iomr_Arg1=1;
- myDoIO(h->mdevreq,MPEGCMD_PAUSE);
- h->mdevport->mp_Flags=PA_SOFTINT;
- h->mhistatus=MHIF_STOPPED;
- }
-
-
-
-
-
- void __asm
- i_MHIPause(register __a3 APTR handle)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- #ifdef DEBUG
- KPutStr("MHIPause()\n");
- #endif
- if(handle==NULL) return;
- if(h->mhistatus==MHIF_PLAYING)
- {
- h->mdevreq->iomr_Arg1=1;
- h->mhistatus=MHIF_PAUSED;
- }
- else if(h->mhistatus==MHIF_PAUSED)
- {
- h->mdevreq->iomr_Arg1=0;
- h->mhistatus=MHIF_PLAYING;
- }
- else return;
- myDoIO(h->mdevreq,MPEGCMD_PAUSE);
- }
-
-
-
-
-
- ULONG __asm
- i_MHIQuery(register __d1 ULONG query)
- {
- #ifdef DEBUG
- KPutStr("MHIQuery()\n");
- #endif
- switch(query)
- {
- case MHIQ_DECODER_NAME:
- return((ULONG)"MHI driver for mpeg.device");
- case MHIQ_DECODER_VERSION:
- return((ULONG)IDSTRING);
- case MHIQ_AUTHOR:
- return((ULONG)"Michael Henke");
- case MHIQ_IS_HARDWARE:
- return(MHIF_TRUE);
- case MHIQ_LAYER1:
- case MHIQ_LAYER2:
- case MHIQ_LAYER3:
- /* mpeg.device is able to tell us but we can't access it from here */
- /* we would need an initialised mhimdevHandle for this... */
- return(MHIF_SUPPORTED);
- case MHIQ_MPEG1:
- case MHIQ_MPEG2:
- case MHIQ_MPEG25:
- case MHIQ_VARIABLE_BITRATE:
- case MHIQ_JOINT_STERIO:
- /* mpeg.device can't tell us these things but we are optimistic */
- return(MHIF_SUPPORTED);
- case MHIQ_VOLUME_CONTROL:
- case MHIQ_PANNING_CONTROL:
- /* these are standard features of mpeg.device */
- return(MHIF_SUPPORTED);
- default:
- /* everything else is either MHIF_FALSE or MHIF_UNSUPPORTED ;-) */
- return(MHIF_UNSUPPORTED);
- }
- }
-
-
-
-
-
- void __asm
- i_MHISetParam(register __a3 APTR handle, register __d0 UWORD param, register __d1 ULONG value)
- {
- struct mhimdevHandle *h = (struct mhimdevHandle*) handle;
- struct MPEGAudioParams map;
- ULONG vol;
- #ifdef DEBUG
- KPutStr("MHISetParam()\n");
- #endif
- if(handle==NULL) return;
- if(param==MHIP_VOLUME) h->mhivolume=(value>100 ? 100 : value);
- else if(param==MHIP_PANNING) h->mhipanning=(value>100 ? 100 : value);
- else return;
- vol=0xffff*h->mhivolume;
- map.map_VolumeLeft =(vol*(ULONG)(h->mhipanning>50 ? 100-h->mhipanning : 50))/5000;
- map.map_VolumeRight=(vol*(ULONG)(h->mhipanning<50 ? h->mhipanning : 50))/5000;
- map.map_StreamID=0xffff;
- h->mdevreq->iomr_Req.io_Data= ↦
- h->mdevreq->iomr_Req.io_Length=sizeof(struct MPEGAudioParams);
- myDoIO(h->mdevreq,MPEGCMD_SETAUDIOPARAMS);
- }
-
-
-
-
-
- /*** private routines ***/
-
- static void
- myDoIO(struct IOMPEGReq *mdevreq, UWORD command)
- {
- mdevreq->iomr_Req.io_Command=command;
- mdevreq->iomr_Req.io_Flags=0;
- mdevreq->iomr_StreamType=MPEGSTREAM_AUDIO;
- DoIO((struct IORequest*)mdevreq);
- }
-
-
- static void __asm
- softint_server(register __a1 struct mhimdevHandle *h)
- {
- struct IOMPEGReq *req;
- #ifdef DEBUG
- KPutStr("--softint_server\n");
- #endif
- while((req=(struct IOMPEGReq*)GetMsg(h->mdevport)))
- {
- if(req!=h->mdevreq)
- {
- AddTail(&h->list_getempty,(struct Node*)req);
- h->requests_pending--;
- }
- }
- Signal(h->mhitask,h->mhisignal);
- }
-
-